//
//package core
//{
//import chisel3._
//import chisel3.util._
//import chisel3.util.experimental.BoringUtils
//import common.Constants._
//import bus._
//import top.AddrSpace
//
//class ExetoMemIO() extends Bundle() {
//  val instValid = Output(Bool())
//  val pc = Output(UInt(64.W))
//  val inst = Output(UInt(32.W))
//  val alu_out = Output(UInt(DataBits.W))
//  val rs2_data = Output(UInt(DataBits.W))
//  val pc_sel = Output(UInt(PC_4.getWidth.W))
//  val mem_en = Output(Bool())
//  val mem_typ = Output(UInt(MT_X.getWidth.W))
//  val mem_fun = Output(UInt(1.W))
//  val rf_wen = Output(Bool())
//  val wb_sel = Output(UInt(WB_X.getWidth.W))
//  val wb_addr = Output(UInt(5.W))
//  val csr_cmd = Output(UInt(CSR.SZ))
//}
//  class WBCommitBus extends Bundle() {
//    val instValid = Output(Bool())
//    val inst = Output(UInt(32.W))
//    val pc = Output(UInt(DataBits.W))
//    val rf_wen = Output(Bool())
//    val wb_addr = Output(UInt(5.W))
//    val wb_data = Output(UInt(DataBits.W))
//    val mem_reg_pc = Output(UInt(32.W))
//    val is_mmio = Output(Bool())
//  }
//
//
//  class MEMStage() extends Module {
//    val io = IO(new Bundle() {
//      val flush = Input(Bool())
//      val in = Flipped(Decoupled(new ExetoMemIO))
//      val out = Decoupled(new WBCommitBus())
//      val dmem = new CoreLinkIO(DataBits)
//      val mmio = new CoreLinkIO(DataBits)
//      val bypass = Flipped(new ByPassDataIO)
//      val csr = Flipped(new CSRRWBUS())
//    })
//
//    io := DontCare
//
//    val reset_mem = WireInit(0.U.asTypeOf(new ExetoMemIO))
//    reset_mem.inst := BUBBLE
////    val idle :: req :: resp :: Nil = Enum(3)
////    val memState = RegInit(idle)
////    switch(memState){
////      is(idle){
////        when(io.in.bits.mem_en){ memState := req }
////      }
////      is(req){
////        when(io.mmio.req.fire() || io.dmem.req.fire()){ memState := resp }
////      }
////      is(resp){
////        when(io.out.fire()){
////          when(io.in.fire() && io.in.bits.mem_en){ memState := req }.otherwise{ memState := idle }
////        }
////      }
////    }
//
//
//
//    // ===== pipelien reg =====
//    val mem_reg = RegInit(reset_mem)
//
//    io.in.ready :=  Mux(!mem_reg.mem_en, io.out.ready, io.out.fire())
//
//    // *********************************
//    // update the mem reg stage
//    when(io.in.fire() && io.out.fire() && !io.flush) {
//      mem_reg := io.in.bits
//    }.elsewhen((!io.in.fire() && io.out.fire()) || io.flush) {
//      mem_reg := reset_mem
//    }
//
//    // ===================== mem stage status =======================
//    val load_data = WireInit(0.U(DataBits.W))
//    val is_mmio = Wire(Bool())
//    val shift = (mem_reg.alu_out(2, 0) << 3)
//    val addrAtMMIO = AddrSpace.isMMIO(mem_reg.alu_out)
//    is_mmio := mem_reg.mem_en && addrAtMMIO//(mem_reg.alu_out < 0x80000000L.U)
//    when(mem_reg.mem_en && ((!is_mmio && io.dmem.resp.fire()) || (is_mmio && io.mmio.resp.fire()))) {
//      load_data := Mux(is_mmio, io.mmio.resp.bits.rdata, io.dmem.resp.bits.rdata)
//    }
//
//    // ========================= CSR ============================
//    io.csr.addr := Mux(mem_reg.csr_cmd === CSR.N, 0.U, mem_reg.inst(31, 20))
//    io.csr.cmd := mem_reg.csr_cmd
//    io.csr.wdata := mem_reg.alu_out
//    val csr_rdata = io.csr.rdata
//    io.csr.rd := mem_reg.wb_addr
//    io.csr.pc := mem_reg.pc
//    io.csr.instValidnoComplete := mem_reg.instValid && !io.out.fire()
//
//    // ========================= linking the mem or mmio ============================
//    // write data
//    val wdata = MuxCase(mem_reg.rs2_data(DataBits - 1, 0), Array(
//      (mem_reg.mem_typ === MT_D)    ->  mem_reg.rs2_data(63, 0),
//      (mem_reg.mem_typ === MT_W)    ->  mem_reg.rs2_data(31, 0),
//      (mem_reg.mem_typ === MT_H)    ->  mem_reg.rs2_data(15, 0),
//      (mem_reg.mem_typ === MT_B)    ->  mem_reg.rs2_data(7, 0),
//    )).asUInt()
//    // val shift_wdata = (wdata << shift).asUInt()
//    // AXI axsize
//    val size = Mux(mem_reg.mem_typ === MT_X, 0.U,
//               Mux(mem_reg.mem_typ === MT_B || mem_reg.mem_typ === MT_BU,  0.U,
//               Mux(mem_reg.mem_typ === MT_H || mem_reg.mem_typ === MT_HU,  1.U,
//               Mux(mem_reg.mem_typ === MT_W || mem_reg.mem_typ === MT_WU,  2.U,
//                  3.U))))
//    // memory
//    val memCmd = Mux(mem_reg.mem_fun === M_XWR, LinkBusCmd.writeLast, LinkBusCmd.read)
//    io.dmem.req.valid := mem_reg.mem_en && !is_mmio
//    io.dmem.req.bits.addr := Mux(mem_reg.mem_en && !is_mmio, mem_reg.alu_out, 0.U)
//    io.dmem.req.bits.wdata := Mux(mem_reg.mem_en && !is_mmio, wdata, 0.U)
//    io.dmem.req.bits.cmd := Mux(mem_reg.mem_en && !is_mmio, memCmd, 0.U)
//    io.dmem.req.bits.size := Mux(mem_reg.mem_en && !is_mmio, size, 0.U)
//    io.dmem.resp.ready := true.B
//    // mmio
//    io.mmio.req.valid := mem_reg.mem_en && is_mmio
//    io.mmio.req.bits.addr := Mux(mem_reg.mem_en && is_mmio, mem_reg.alu_out, 0.U)
//    io.mmio.req.bits.wdata := Mux(mem_reg.mem_en && is_mmio, wdata, 0.U)
//    io.mmio.req.bits.cmd := Mux(mem_reg.mem_en && is_mmio, memCmd, 0.U)
//    io.mmio.req.bits.size := Mux(mem_reg.mem_en && is_mmio, size, 0.U)
//    io.mmio.resp.ready := true.B
//
//    // =================== write back data ============================
//    val wb_ld_data = MuxCase(load_data, Array(
//      (mem_reg.mem_typ === MT_B)   -> Cat(Fill(DataBits -  8, load_data(7)),   load_data(7, 0)),
//      (mem_reg.mem_typ === MT_H)   -> Cat(Fill(DataBits - 16, load_data(15)),  load_data(15, 0)),
//      (mem_reg.mem_typ === MT_W)   -> Cat(Fill(DataBits - 32, load_data(31)),  load_data(31, 0)),
//      (mem_reg.mem_typ === MT_BU)  -> Cat(Fill(DataBits -  8, 0.U),                load_data(7, 0)),
//      (mem_reg.mem_typ === MT_HU)  -> Cat(Fill(DataBits - 16, 0.U),                load_data(15, 0)),
//      (mem_reg.mem_typ === MT_WU)  -> Cat(Fill(DataBits - 32, 0.U),                load_data(31, 0))
//    ))
//
//    val mem_wb_data = MuxCase(mem_reg.alu_out, Array(
//      (mem_reg.wb_sel === WB_ALU)  ->  mem_reg.alu_out,
//      (mem_reg.wb_sel === WB_MEM)  ->  wb_ld_data,
//      (mem_reg.wb_sel === WB_PC4)  ->  (mem_reg.pc + 4.U),
//      (mem_reg.wb_sel === WB_CSR)  ->  csr_rdata
//    ))
//
//    // ===================== output next stage ===================
//    io.out.valid := Mux(!mem_reg.mem_en, true.B, Mux(is_mmio, io.mmio.resp.valid, io.dmem.resp.valid))
//    io.out.bits.instValid := mem_reg.instValid
//    io.out.bits.pc := mem_reg.pc
//    io.out.bits.inst := mem_reg.inst
//    io.out.bits.rf_wen := mem_reg.rf_wen
//    io.out.bits.wb_addr := mem_reg.wb_addr
//    io.out.bits.wb_data := mem_wb_data
//    io.out.bits.is_mmio := is_mmio
//
//    // ================ ByPass =====================
//    io.bypass.apply(rf_wen = mem_reg.rf_wen, addr = mem_reg.wb_addr, data = mem_wb_data)
//
//  }
//
//}